<!DOCTYPE html>
<html lang="zh-CN">





<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" type="image/png" href="/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="">
  <meta name="author" content="Peng">
  <meta name="keywords" content="">
  <title>XO棋子的实现 - 伍志鹏的技术分享</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/github-gist.min.css" />
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_yg9cfy8wd6.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_pjno9b9zyxs.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/js/utils.js" ></script>
<meta name="generator" content="Hexo 5.0.2"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>Peng's space</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                友链
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="view intro-2" id="background" parallax=true
         style="background: url('/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container text-center white-text fadeInUp">
            <span class="h2" id="subtitle">
              
            </span>

            
              
  <div class="mt-3 post-meta">
    <i class="iconfont icon-date-fill" aria-hidden="true"></i>
    <time datetime="2020-09-01 16:37">
      2020年9月1日 下午
    </time>
  </div>


<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      1k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      14
       分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <div class="post-content mx-auto" id="post">
            
            <article class="markdown-body">
              <p>下棋游戏（XXOO）</p>
<h4 id="项目地址"><a href="#项目地址" class="headerlink" title="项目地址"></a>项目地址</h4><p><a target="_blank" rel="noopener" href="https://github.com/UserNameInExistence/XO_Pieces">https://github.com/UserNameInExistence/XO_Pieces</a></p>
<h4 id="下棋游戏总结（XXOO）"><a href="#下棋游戏总结（XXOO）" class="headerlink" title="下棋游戏总结（XXOO）"></a>下棋游戏总结（XXOO）</h4><ol>
<li>使用学到的 TS 、Web 开发知识，完成了下棋游戏。</li>
<li>TS 知识：变量声明、枚举、类型断言、函数（参数、返回值）等。</li>
<li>枚举：是一组有名字的常量的集合，用来组织有关联的数据。</li>
<li>类型断言：在我们比 TS 更明确变量的类型时，来指定具体类型。</li>
<li>函数封装：主要考虑参数和返回值，也就是接收要处理的数据，返回处理后<br>的结果。</li>
<li>实现功能：分步骤实现，完成一步，验证一步（先实现，再优化）。</li>
<li>DOM 操作：获取元素、添加移除事件、事件对象、样式操作、文本内容。</li>
<li>伪数组：具有长度（length）属性和索引（长得像、操作也像数组）。</li>
</ol>
<h5 id="typescript部分源码"><a href="#typescript部分源码" class="headerlink" title="typescript部分源码"></a>typescript部分源码</h5><pre><code class="hljs typescript"><span class="hljs-comment">// 一.单元格点击</span>
<span class="hljs-comment">// 二.下完棋切换玩家</span>
<span class="hljs-comment">// 三.变量使用枚举</span>
<span class="hljs-comment">// 四.判赢函数</span>
<span class="hljs-comment">// 五.判断平局</span>
<span class="hljs-comment">// 六.展示获胜信息</span>
<span class="hljs-comment">// 七.重新开始游戏</span>
<span class="hljs-comment">// 3.1 创建字符串枚举Player</span>
<span class="hljs-built_in">enum</span> Player&#123;
    X = <span class="hljs-string">&#x27;x&#x27;</span>,
    O = <span class="hljs-string">&#x27;o&#x27;</span>
&#125;
<span class="hljs-comment">// 1.1 cells获取到所有的单元格列表元素cell</span>
<span class="hljs-keyword">let</span> cells = <span class="hljs-built_in">document</span>.querySelectorAll(<span class="hljs-string">&#x27;.cell&#x27;</span>)
<span class="hljs-comment">// 2.1 创建一个存储当前玩家的变量currentPlayer，默认值为Player.X</span>
<span class="hljs-keyword">let</span> currentPlayer: Player
<span class="hljs-comment">// gameBord以及获取游戏面板元素bord</span>
<span class="hljs-keyword">let</span> gameBord = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">&#x27;#bord&#x27;</span>)
<span class="hljs-comment">// 6.1 message获取获胜信息面板元素message</span>
<span class="hljs-keyword">let</span> message = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">&#x27;#message&#x27;</span>) <span class="hljs-keyword">as</span> HTMLDivElement
<span class="hljs-comment">// winner以及获取获胜者元素winner</span>
<span class="hljs-keyword">let</span> winner = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">&#x27;#winner&#x27;</span>) <span class="hljs-keyword">as</span> HTMLParagraphElement
<span class="hljs-comment">// 7.1 restart获取按钮元素restart</span>
<span class="hljs-keyword">let</span> restart = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">&#x27;#restart&#x27;</span>) <span class="hljs-keyword">as</span> HTMLButtonElement
<span class="hljs-comment">// 4.2 创建胜利数组</span>
<span class="hljs-keyword">let</span> winsArr = [
    [<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>],[<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>],[<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>],    <span class="hljs-comment">//三行</span>
    [<span class="hljs-number">0</span>,<span class="hljs-number">3</span>,<span class="hljs-number">6</span>],[<span class="hljs-number">1</span>,<span class="hljs-number">4</span>,<span class="hljs-number">7</span>],[<span class="hljs-number">2</span>,<span class="hljs-number">5</span>,<span class="hljs-number">8</span>],    <span class="hljs-comment">//三列</span>
    [<span class="hljs-number">0</span>,<span class="hljs-number">4</span>,<span class="hljs-number">8</span>],[<span class="hljs-number">2</span>,<span class="hljs-number">4</span>,<span class="hljs-number">6</span>]             <span class="hljs-comment">//两斜</span>
]
<span class="hljs-comment">// 5.1 记录下棋次数</span>
<span class="hljs-keyword">let</span> steps: <span class="hljs-built_in">number</span>
<span class="hljs-comment">/* </span>
<span class="hljs-comment">cells.forEach(function(item)&#123;</span>
<span class="hljs-comment">    // 1.2 遍历单元格列表，给每一个单元格添加点击事件</span>
<span class="hljs-comment">    let cell = item as HTMLDivElement</span>
<span class="hljs-comment">    cell.addEventListener(&#x27;click&#x27;,clickCell,&#123;once:true&#125;)</span>
<span class="hljs-comment">&#125;)</span>
<span class="hljs-comment"> */</span>
startGame()

restart.addEventListener(<span class="hljs-string">&#x27;click&#x27;</span>, startGame)

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">startGame</span>(<span class="hljs-params"></span>)</span>&#123;
    <span class="hljs-comment">// 隐藏获胜信息、重置下棋次数、设置默认玩家、重置下棋提示</span>
    message.style.display = <span class="hljs-string">&#x27;none&#x27;</span>
    steps = <span class="hljs-number">0</span>
    currentPlayer = Player.X
    gameBord.classList.remove(Player.X, Player.O)
    gameBord.classList.add(Player.X)

    cells.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">item</span>)</span>&#123;
        <span class="hljs-keyword">let</span> cell = item <span class="hljs-keyword">as</span> HTMLDivElement
        <span class="hljs-comment">// 清空棋盘</span>
        cell.classList.remove(Player.X, Player.O)
        <span class="hljs-comment">// 移除单元格点击事件，重新绑定单击事件</span>
        cell.removeEventListener(<span class="hljs-string">&#x27;click&#x27;</span>, clickCell)
        cell.addEventListener(<span class="hljs-string">&#x27;click&#x27;</span>, clickCell,&#123;once:<span class="hljs-literal">true</span>&#125;)
        &#125;)
&#125;

<span class="hljs-comment">// 1.封装点击函数</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">clickCell</span>(<span class="hljs-params">event:MouseEvent</span>) </span>&#123;
    <span class="hljs-comment">// 1.3 给当前被点击的单元格添加类名</span>
    <span class="hljs-keyword">let</span> target = event.target <span class="hljs-keyword">as</span> HTMLDivElement
    <span class="hljs-comment">// 2.2 添加单元格类名添加变量</span>
    target.classList.add(currentPlayer)
    <span class="hljs-comment">// 5.2 下棋次数自增一次</span>
    steps++
    <span class="hljs-comment">// 4.1 调用判赢函数来判断是否获胜</span>
    <span class="hljs-keyword">let</span> isWin = checkWin(currentPlayer)
    <span class="hljs-keyword">if</span>(isWin) &#123;
        <span class="hljs-comment">// 6.2 显示获胜信息面板</span>
        message.style.display = <span class="hljs-string">&#x27;block&#x27;</span>
        <span class="hljs-comment">// 6.3 设置获胜文本</span>
        winner.innerText = currentPlayer + <span class="hljs-string">&#x27; 赢了！&#x27;</span>
        <span class="hljs-keyword">return</span>
    &#125;
    <span class="hljs-comment">// 5.3 判断是否下了9次棋（平局）</span>
    <span class="hljs-keyword">if</span>(steps === <span class="hljs-number">9</span>) &#123;
        message.style.display = <span class="hljs-string">&#x27;block&#x27;</span>
        winner.innerText = <span class="hljs-string">&#x27;平局。&#x27;</span>
        <span class="hljs-keyword">return</span>
    &#125;
    <span class="hljs-comment">// 2.3 下完棋后切换到另一个玩家</span>
    currentPlayer = currentPlayer === Player.X ? Player.O : Player.X
    <span class="hljs-comment">// 2.4 处理下一步提示</span>
    gameBord.classList.remove(Player.X,Player.O)
    gameBord.classList.add(currentPlayer)
&#125;

<span class="hljs-comment">// 4.3 封装判赢函数</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkWin</span>(<span class="hljs-params">player:Player</span>) </span>&#123;
    <span class="hljs-comment">// 4.3.1 使用some方法遍历winsArr二维数组</span>
    <span class="hljs-comment">// some()方法测试数组中是不是至少有1个元素通过了被提供的函数测试。</span>
    <span class="hljs-keyword">return</span> winsArr.some(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">item</span>) </span>&#123;
        <span class="hljs-comment">// 4.3.2 获取每种胜利情况的三个索引</span>
        <span class="hljs-keyword">let</span> cellIndex1 = item[<span class="hljs-number">0</span>]
        <span class="hljs-keyword">let</span> cellIndex2 = item[<span class="hljs-number">1</span>]
        <span class="hljs-keyword">let</span> cellIndex3 = item[<span class="hljs-number">2</span>]
        <span class="hljs-comment">// 4.3.3 通过索引从cells单元格中获取对应的单元格元素（优化精简）</span>

        <span class="hljs-comment">// 4.3.4 判断3个单元格元素是否同时包含当前玩家的类名Player</span>
        <span class="hljs-keyword">if</span>(
            hasClass(cells[cellIndex1], player) &amp;&amp;
            hasClass(cells[cellIndex2], player) &amp;&amp;
            hasClass(cells[cellIndex3], player)
        ) &#123;
            <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
        &#125;
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
    &#125;)
&#125;

<span class="hljs-comment">// 4.3.5 封装判断DOM元素是否包含某个类名</span>
<span class="hljs-comment">// classList.contains（）方法判断html元素是否包含变量</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hasClass</span>(<span class="hljs-params">el: Element, name: <span class="hljs-built_in">string</span></span>) </span>&#123;
    <span class="hljs-keyword">return</span> el.classList.contains(name)
&#125;</code></pre>


            </article>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/TypeScript/">TypeScript</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/%E5%89%8D%E7%AB%AF/">前端</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <div class="post-prev col-6">
                    
                    
                  </div>
                  <div class="post-next col-6">
                    
                    
                      <a href="/2020/09/01/git%E5%85%8B%E9%9A%86%E9%83%A8%E5%88%86%E6%96%87%E4%BB%B6/">
                        <span class="hidden-mobile">git克隆部分文件</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </div>
                </div>
              
            </div>

            
              <!-- Comments -->
              <div class="comments" id="comments">
                
                
  <div id="vcomments"></div>
  <script type="text/javascript">
    function loadValine() {
      addScript('https://cdn.staticfile.org/valine/1.4.14/Valine.min.js', function () {
        new Valine({
          el: "#vcomments",
          app_id: "9xTfBJPOSPHPdr8Ep3JUyVQE-9Nh9j0Va",
          app_key: "Hf8Td0FLQMk2rpkUwhB88Oc8",
          placeholder: "说点什么",
          path: window.location.pathname,
          avatar: "retro",
          meta: ["nick","mail","link"],
          pageSize: "10",
          lang: "zh-CN",
          highlight: false,
          recordIP: false,
          serverURLs: "https://9xtfbjpo.lc-cn-e1-shared.com",
        });
      });
    }
    createObserver(loadValine, 'vcomments');
  </script>
  <noscript>Please enable JavaScript to view the <a target="_blank" href="https://valine.js.org" rel="nofollow noopener noopener">comments
      powered by Valine.</a></noscript>


              </div>
            
          </div>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  

  <footer class="mt-5">
  <div class="text-center py-3">
    <div>
      <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a>
      <i class="iconfont icon-love"></i>
      <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener">
        <span>Fluid</span></a>
    </div>
    

    

    
  </div>
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/js/debouncer.js" ></script>
<script  src="/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/lazyload.js" ></script>
  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/js/clipboard-use.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: 'article.markdown-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "XO棋子的实现&nbsp;",
      ],
      cursorChar: "_",
      typeSpeed: 70,
      loop: false,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>



  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/js/local-search.js" ></script>
  <script>
    var path = "/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>




















</body>
</html>
